package com.sfang.common.util.concurrent;

import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.Set;
import java.util.concurrent.*;
import java.util.function.Supplier;

public class ThreadUtils {
    protected static ExecutorService EXECUTOR_SERVICE = Executors.newFixedThreadPool(100);

    protected static Logger LOGGER = LoggerFactory.getLogger(ThreadUtils.class);

    public static <T> Future<T> parallelTasks(Supplier<T> task) {

        Future<T> future = EXECUTOR_SERVICE.submit(new Callable<T>() {
            @Override
            public T call() throws Exception {
                return task.get();
            }
        });

        return future;
    }

    public static <T> void parallelTasksWithoutFuture(Runnable task) {
        EXECUTOR_SERVICE.submit(task);
    }

    public static void parallelTasks(List<Supplier> suppliers) {

        CompletionService completionService = new ExecutorCompletionService(EXECUTOR_SERVICE);

        for (Supplier supplier : suppliers)
            completionService.submit(new Callable() {
                @Override
                public Object call() throws Exception {
                    return supplier.get();
                }
            });

        try {
            for (int i = 0; i < suppliers.size(); i++)
                completionService.take().get();
        } catch (Exception e) {
            LOGGER.error(String.format("parallelTasks error:%s", JSON.toJSONString(e)));
            throw new RuntimeException(e);
        }

        LOGGER.warn(String.format("all task finished,size:%s", suppliers.size()));
    }

    public static void parallelRunnables(Set<Runnable> runnables) {

        CompletionService completionService = new ExecutorCompletionService(EXECUTOR_SERVICE);

        for (Runnable runnable : runnables)
            completionService.submit(runnable, null);

        try {
            for (int i = 0; i < runnables.size(); i++)
                completionService.take().get();
        } catch (Exception e) {
            LOGGER.error("parallelRunnables error:", e);
            throw new RuntimeException(e);
        }

        LOGGER.warn("all runnable finished,size:{}", runnables.size());
    }
}
